package com.hanxiaozhang.threadbase1ndedition.no10threadpool;

import java.io.IOException;
import java.util.concurrent.*;

/**
 * 〈一句话功能简述〉<br>
 * 〈线程池拒绝策略〉
 *
 * @author hanxinghua
 * @create 2021/11/25
 * @since 1.0.0
 */
public class No6ThreadPoolPolicy {

    public static void main(String[] args) {

        // AbortPolicy中止策略（默认）
        // abortPolicy();

        // DiscardPolicy抛弃策略，抛弃最新的
        // discardPolicy();

        // DiscardOldestPolicy抛弃最旧的策略
        //discardOldestPolicy();

        // CallerRunsPolicy调用者运行策略
        // callerRunsPolicy();

        // CustomPolicy自定义策略
        customPolicy();

    }


    /**
     * AbortPolicy中止策略（默认）
     */
    private static void abortPolicy() {
        ThreadPoolExecutor threadPool = new ThreadPoolExecutor(2, 4,
                60, TimeUnit.SECONDS,
                new ArrayBlockingQueue<Runnable>(4),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy());
        for (int i = 0; i < 8; i++) {
            threadPool.execute(new Task(i));
        }
        System.out.println(threadPool.getQueue());
        threadPool.execute(new Task(100));
        System.out.println(threadPool.getQueue());
        threadPool.shutdown();
    }

    /**
     * DiscardPolicy抛弃策略
     */
    private static void discardPolicy() {
        ThreadPoolExecutor threadPool = new ThreadPoolExecutor(2, 4,
                60, TimeUnit.SECONDS,
                new ArrayBlockingQueue<Runnable>(4),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.DiscardPolicy());
        for (int i = 0; i < 8; i++) {
            threadPool.execute(new Task(i));
        }
        System.out.println(threadPool.getQueue());
        threadPool.execute(new Task(100));
        System.out.println(threadPool.getQueue());
        threadPool.shutdown();
    }

    /**
     * DiscardOldestPolicy抛弃最旧的策略
     */
    private static void discardOldestPolicy() {
        ThreadPoolExecutor threadPool = new ThreadPoolExecutor(2, 4,
                60, TimeUnit.SECONDS,
                new ArrayBlockingQueue<Runnable>(4),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.DiscardOldestPolicy());
        for (int i = 0; i < 8; i++) {
            threadPool.execute(new Task(i));
        }
        System.out.println(threadPool.getQueue());
        threadPool.execute(new Task(100));
        System.out.println(threadPool.getQueue());
        threadPool.shutdown();
    }

    /**
     * CallerRunsPolicy调用者运行策略
     */
    private static void callerRunsPolicy() {
        ThreadPoolExecutor threadPool = new ThreadPoolExecutor(2, 4,
                60, TimeUnit.SECONDS,
                new ArrayBlockingQueue<Runnable>(4),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.CallerRunsPolicy());
        for (int i = 0; i < 8; i++) {
            threadPool.execute(new Task(i));
        }
        System.out.println(threadPool.getQueue());
        threadPool.execute(new Task(100));
        System.out.println(threadPool.getQueue());
        threadPool.shutdown();
    }

    /**
     * CustomPolicy自定义策略
     */
    private static void customPolicy() {
        ThreadPoolExecutor threadPool = new ThreadPoolExecutor(2, 4,
                60, TimeUnit.SECONDS,
                new ArrayBlockingQueue<Runnable>(4),
                Executors.defaultThreadFactory(),
                new CustomPolicy());
        for (int i = 0; i < 8; i++) {
            threadPool.execute(new Task(i));
        }
        System.out.println(threadPool.getQueue());
        threadPool.execute(new Task(100));
        System.out.println(threadPool.getQueue());
        threadPool.shutdown();
    }

    /**
     * 自定义策略
     */
    static class CustomPolicy implements RejectedExecutionHandler {

        public CustomPolicy() {
        }

        @Override
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            if (!e.isShutdown()) {
                System.out.println("把任务存入Kafka等中间件");
            }
        }
    }

    static class Task implements Runnable {
        private int i;

        public Task(int i) {
            this.i = i;
        }

        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName() + " Task " + i);
            try {
                System.in.read();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        @Override
        public String toString() {
            return "Task{" + "i=" + i + '}';
        }

    }

}
